import generate from "@babel/generator"
import { parse } from "@babel/parser"
import traverse, { NodePath } from "@babel/traverse"
import * as types from "@babel/types"
import * as prettier from "prettier"

import fs from "node:fs"

let prettierOptions: prettier.Options | null = null

/**
 * 解析并读取项目根目录的prettier配置
 */
const resolvePrettierOptions = async () => {
  try {
    const prettierConfigFile = await prettier.resolveConfigFile()

    if (prettierConfigFile) {
      const options = await prettier.resolveConfig(prettierConfigFile)
      console.log("项目的配置文件对象")
      console.log(options)

      prettierOptions = options
    }
  } catch (error) {
    console.log("prettier 解析配置文件")
  }
}

// 改动过的文件
const modifyFiles = new Set()

/**
 * 重新生成一个箭头函数
 * @param str
 */
function genArrowFunction(str: string): types.ArrowFunctionExpression {
  return types.arrowFunctionExpression(
    [],
    types.importExpression(types.stringLiteral(str))
  )
}

const changeByArrowFunctionExpression = (
  path: NodePath<types.ArrowFunctionExpression>,
  file: String
) => {
  // 从函数调体里面拿到 组件的路径

  const node = path.node as types.ArrowFunctionExpression

  const body = node.body as types.CallExpression

  if (!body.arguments) return

  if (types.isArrayExpression(body.arguments[0])) {
    let elements = body.arguments[0].elements as Array<types.StringLiteral>

    // 拿到路径字符串
    let routePathStr = elements[0].value

    if (!routePathStr) return

    // 重新构造一个AST节点。 将这块内容替换为 import写法
    const newNode = genArrowFunction(routePathStr)

    // 节点替换
    path.replaceWith(newNode)

    modifyFiles.add(file)
  }
}

const genTasks = (item: string) => {
  return new Promise(async (resolve) => {
    const content = fs.readFileSync(item, {
      encoding: "utf-8"
    })

    let ast = parse(content, {
      sourceType: "module",
      sourceFilename: item
    })

    traverse.default(ast, {
      /**
       * 监听箭头函数
       */
      ArrowFunctionExpression(p: NodePath<types.ArrowFunctionExpression>) {
        changeByArrowFunctionExpression(p, item)
      }
    })

    if (modifyFiles.has(item)) {
      const code = generate.default(ast).code

      // 将代码格式化一下 - 如果解析到项目根目录有 prettier的配置
      if (prettierOptions) {
        let res = await prettier.format(code, {
          ...prettierOptions,
          // 让prettier自行根据文件路径的后缀决定使用什么  parser解析器解析代码（可兼容ts,js, jsx等场景）
          filepath: item
        })

        // 将修改后的内容写入到文件
        fs.writeFileSync(item, res)
      } else {
        // 将修改后的内容写入到文件
        fs.writeFileSync(item, generate.default(ast).code)
      }
    }

    resolve(void 0)
  })
}

export default async (list: Array<string>) => {
  await resolvePrettierOptions()

  const allTasks = list.map((item) => genTasks(item))

  try {
    await Promise.all(allTasks)

    console.log("转换完成")

    let arr = Array.from(modifyFiles)

    console.log("有require的文件清单", `【${arr.length}】个`)
    console.log(arr)
  } catch (error) {
    console.log("转换失败")

    console.log(error)
  }
}
